package com.ruoyi.wb.service.impl;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.json.JSONUtil;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.PageUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.system.mapper.SysUserMapper;
import com.ruoyi.wb.domain.*;
import com.ruoyi.wb.dto.DeviceRenewInfoDto;
import com.ruoyi.wb.dto.WbRepairApplyDto;
import com.ruoyi.wb.enmus.RoleNameEnums;
import com.ruoyi.wb.enmus.WbInformType;
import com.ruoyi.wb.enmus.WbRepairApplyOrderType;
import com.ruoyi.wb.mapper.WbEntAuthMapper;
import com.ruoyi.wb.mapper.WbInformMapper;
import com.ruoyi.wb.mapper.WbRepairApplyMapper;
import com.ruoyi.wb.mapper.WbRepairOrderMapper;
import com.ruoyi.wb.service.IWbEntAuthService;
import com.ruoyi.wb.service.IWbMaintainCompanyService;
import com.ruoyi.wb.service.IWbRepairApplyService;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.math.BigDecimal;
import java.util.*;

/**
 * 报修申请Service业务层处理
 * 
 * @author ruoyi
 * @date 2024-10-14
 */
@Service
@AllArgsConstructor
public class WbRepairApplyServiceImpl  implements IWbRepairApplyService
{

    private final WbRepairApplyMapper wbRepairApplyMapper;


    private final WbRepairOrderMapper wbRepairOrderMapper;


    private final WbEntAuthMapper wbEntAuthMapper;


    private final IWbEntAuthService iWbEntAuthService;


    private  final WbInformMapper wbInformMapper;


    private final IWbMaintainCompanyService iWbMaintainCompanyService;

private  final SysUserMapper sysUserMapper;


    /**
     * 查询报修申请
     * 
     * @param id 报修申请主键
     * @return 报修申请
     */
    @Override
    public WbRepairApply selectWbRepairApplyById(Long id)
    {
        return wbRepairApplyMapper.selectWbRepairApplyById(id);
    }

    /**
     * 查询报修申请列表
     * 
     * @param wbRepairApplyDto 报修申请
     * @return 报修申请
     */
    @Override
    public List<WbRepairApply> selectWbRepairApplyList(WbRepairApplyDto wbRepairApplyDto)
    {
        SysUser user = SecurityUtils.getLoginUser().getUser();
        List<SysRole> roles = user.getRoles();

        List<WbMaintainCompany> wbMaintainCompanies = iWbMaintainCompanyService.selectWbMaintainCompanyByUserId(user.getUserId());
//        if (!CollectionUtils.isEmpty(wbMaintainCompanies)){
//
//        }

        for (SysRole role : roles) {
          if (role.getRoleName().equals(RoleNameEnums.DOMESTIC_CONSUMER.getDescribe())){//普通角色
              wbRepairApplyDto.setApplyerId(user.getUserId());
          }else if(role.getRoleName().equals(RoleNameEnums.REPAIR_MAN.getDescribe())){//外部维修师傅
              wbRepairApplyDto.setRepairerId(user.getUserId());
          }else if(!CollectionUtils.isEmpty(wbMaintainCompanies)){//维保公司角色
              wbRepairApplyDto.setBusinessId(wbMaintainCompanies.get(0).getId());
          }
        }
        PageUtils.startPage();
        return wbRepairApplyMapper.selectWbRepairApplyList(wbRepairApplyDto);
    }

    /**
     * 新增报修申请
     * 
     * @param wbRepairApply 报修申请
     * @return 结果
     */
    @Override
    @Transactional
    public int insertWbRepairApply(WbRepairApply wbRepairApply)
    {
        SysUser sysUser = SecurityUtils.getLoginUser().getUser();
        //用户的企业认证列表
        List<WbEntAuth> wbEntAuths = iWbEntAuthService.selectWbEntAuthListByUserId(sysUser.getUserId());
        //查询维保公司
        List<WbMaintainCompany> wbMaintainCompanies = null;
        //进行报修新增
        wbRepairApply.setApplyerId(sysUser.getUserId()); //设置用户信息
        wbRepairApply.setApplyerName(sysUser.getUserName());
        wbRepairApply.setCreateTime(DateUtils.getNowDate());//设置系统信息
        wbRepairApply.setUpdateTime(DateUtils.getNowDate());
        wbRepairApply.setCreateBy(sysUser.getUserName());
        wbRepairApply.setUpdateBy(sysUser.getUserName());
        wbRepairApply.setStatus(WbRepairApplyOrderType.CANCELLATION.getCode());//设置当前状态
        if (!CollectionUtils.isEmpty(wbEntAuths)){
            //用户企业
            WbEntAuth wbEntAuth = wbEntAuths.get(0);
            wbMaintainCompanies=iWbMaintainCompanyService.selectWbMaintainCompanyByAuthId(wbEntAuth.getId());
            wbRepairApply.setOwnerCompanyId(wbEntAuth.getId()); //设置企业信息
            wbRepairApply.setBusinessId(wbEntAuth.getMaintainCompanyId());
            wbRepairApply.setOwnerCompanyName(wbEntAuth.getEntName());
        }
        int i = wbRepairApplyMapper.insertWbRepairApply(wbRepairApply);
       if (i==0){
           throw new RuntimeException("维修单创建失败");
       }
        //生成订单  如果此次修改状态为 待分配 则已经分配师傅 生成订单 并且发送消息
        if (!ObjectUtils.isEmpty(wbRepairApply.getStatus())&&wbRepairApply.getStatus().equals(WbRepairApplyOrderType.CANCELLATION.getCode())){
            //新增订单
            WbRepairOrder wbRepairOrder = new WbRepairOrder();
            wbRepairOrder.setApplyId(wbRepairApply.getId()); // 维修单 id
            wbRepairOrder.setOrderStatus(WbRepairApplyOrderType.CANCELLATION.getCode());//订单状态
            wbRepairOrder.setArriveTime(DateUtils.parseDate(wbRepairApply.getSubscribeDate()));//上门时间
            wbRepairOrder.setCreateTime(DateUtils.getNowDate());//系统信息
            wbRepairOrder.setUpdateTime(DateUtils.getNowDate());
            wbRepairOrder.setCreateBy(sysUser.getUserName());
            wbRepairOrder.setUpdateBy(sysUser.getUserName());
            wbRepairOrder.setUserId(sysUser.getUserId());//用户信息
            String s = System.currentTimeMillis() + "" + new Random().nextInt(10000);
            wbRepairOrder.setPayOrdernumber(s);
            //查看是否有维保公司 如果有则存维保公司信息
            if (!CollectionUtils.isEmpty(wbMaintainCompanies)){
                WbMaintainCompany wbMaintainCompany = wbMaintainCompanies.get(0);
                wbRepairOrder.setBusinessId(wbMaintainCompany.getId());
                wbRepairOrder.setBusinessName(wbMaintainCompany.getCompanyName());
            }
            int j = wbRepairOrderMapper.insertWbRepairOrder(wbRepairOrder);
            if (j==0){
                throw new RuntimeException("新增订单失败");
            }
            //新增消息
            WbInform wbInform = new WbInform();
            wbInform.setClientId(wbRepairApply.getApplyerId());
            wbInform.setClientName(wbRepairApply.getApplyerName());
            wbInform.setInformType(WbInformType.ORDER_NOTICE.getCode());
            wbInform.setTitle("你有新的订单");
            wbInform.setContent("你报修的设备:"+(ObjectUtils.isEmpty(wbRepairApply.getDevice())?wbRepairApply.getDevice():wbRepairApply.getDevice())
                    +"预约上门时间为:"+ (ObjectUtils.isEmpty(wbRepairApply.getNewArriveTime())?ObjectUtils.isEmpty(wbRepairApply.getNewArriveTime())?ObjectUtils.isEmpty(wbRepairApply.getSubscribeDate())?wbRepairApply.getSubscribeDate():wbRepairApply.getSubscribeDate(): DateUtils.dateTime(wbRepairApply.getNewArriveTime()) :DateUtils.dateTime(wbRepairApply.getNewArriveTime()))
                    +"当前受理状态为:"+WbRepairApplyOrderType.CANCELLATION.getInfo());
            wbInform.setCreateTime(DateUtils.getNowDate());
            wbInform.setCreateBy(sysUser.getUserId().toString());
            wbInform.setUpdateTime(DateUtils.getNowDate());
            wbInform.setUpdateBy(sysUser.getUserId().toString());
            wbInform.setIfRead(WbInformType.UNREAD.getCode());
            wbInform.setDelFlag(WbInformType.EXIST.getCode());
            wbInform.setRelevantBillsId(Long.parseLong(wbRepairOrder.getId()));
            if (wbInformMapper.insertWbInform(wbInform)==0){
                throw new RuntimeException("新增消息失败");
            }

        }
        return i;
    }

    /**
     * 修改报修申请
     * 
     * @param wbRepairApplyDto 报修申请实体
     * @return 结果
     */
    @Override
    @Transactional
    public int updateWbRepairApply(WbRepairApplyDto wbRepairApplyDto)
    {
        SysUser sysUser =null;
        if (ObjectUtils.isEmpty(wbRepairApplyDto.getIfVx())){
             sysUser = SecurityUtils.getLoginUser().getUser();
        }


        WbRepairApply wbRepairApply = BeanUtil.copyProperties(wbRepairApplyDto, WbRepairApply.class);

        WbRepairApply repairApply = wbRepairApplyMapper.selectWbRepairApplyById(wbRepairApplyDto.getId());
        if (ObjectUtils.isEmpty(repairApply)){
            throw new RuntimeException("维修单不存在,修改失败");
        }

        if (!ObjectUtils.isEmpty(wbRepairApply.getStatus())&&wbRepairApply.getStatus().equals(WbRepairApplyOrderType.UNDERWAY.getCode())){
            wbRepairApply.setActualTime(DateUtils.getNowDate());
        }

        int i = wbRepairApplyMapper.updateWbRepairApply(wbRepairApply);
        if (i==0){
            throw new RuntimeException("修改维修单状态失败");
        }

        //分配师傅
        if (!ObjectUtils.isEmpty(wbRepairApplyDto.getStatus())&&wbRepairApplyDto.getStatus().equals(WbRepairApplyOrderType.PENDING_ORDER.getCode())){

            if (ObjectUtils.isEmpty(wbRepairApplyDto.getRepairerId())){
                throw new RuntimeException("维修师傅必填");
            }


            WbRepairOrder wbRepairOrder = new WbRepairOrder();
            wbRepairOrder.setApplyId(wbRepairApply.getId());
            List<WbRepairOrder> wbRepairOrders = wbRepairOrderMapper.selectWbRepairOrderListByApplyId(wbRepairApply.getId());
            if (!CollectionUtils.isEmpty(wbRepairOrders)){
                wbRepairOrder=wbRepairOrders.get(0);
                wbRepairOrder.setMasterIfRead(1);//维修师傅红点
                wbRepairOrderMapper.updateWbRepairOrder(wbRepairOrder);

            }
            SysUser sysUser1 = sysUserMapper.selectUserById(wbRepairApplyDto.getRepairerId());

            //新增消息
            WbInform wbInform = new WbInform();
            wbInform.setClientId(sysUser1.getUserId());

            wbInform.setClientName(sysUser1.getNickName());
            wbInform.setRelevantBillsId(Long.parseLong(wbRepairOrder.getId()));
            wbInform.setInformType(WbInformType.ORDER_NOTICE.getCode());
            wbInform.setTitle("你有新的订单");
            wbInform.setContent("用户报修设备:"+(ObjectUtils.isEmpty(wbRepairApplyDto.getDevice())?repairApply.getDevice():wbRepairApplyDto.getDevice())
                    +"预约上门时间为:"+ (ObjectUtils.isEmpty(wbRepairApplyDto.getNewArriveTime())?ObjectUtils.isEmpty(repairApply.getNewArriveTime())?ObjectUtils.isEmpty(wbRepairApplyDto.getSubscribeDate())?repairApply.getSubscribeDate():wbRepairApplyDto.getSubscribeDate(): DateUtils.dateTime(repairApply.getNewArriveTime()) :DateUtils.dateTime(wbRepairApplyDto.getNewArriveTime()))
                    +"当前受理状态为:"+WbRepairApplyOrderType.getMessage(wbRepairApplyDto.getStatus()));
            wbInform.setCreateTime(DateUtils.getNowDate());

            if (ObjectUtils.isEmpty(wbRepairApplyDto.getIfVx())){
                wbInform.setCreateBy(sysUser.getUserName());
                wbInform.setUpdateBy(sysUser.getUserName());
            }
            wbInform.setUpdateTime(DateUtils.getNowDate());
            wbInform.setIfRead(WbInformType.UNREAD.getCode());
            wbInform.setDelFlag(WbInformType.EXIST.getCode());
            if (wbInformMapper.insertWbInform(wbInform)==0){
                throw new RuntimeException("新增信息失败");
            }
        }



        wbRepairApply.setUpdateTime(DateUtils.getNowDate());
        //给订单同步状态
        WbRepairOrder wbRepairOrder = new WbRepairOrder();
        wbRepairOrder.setApplyId(wbRepairApply.getId());
        List<WbRepairOrder> wbRepairOrders = wbRepairOrderMapper.selectWbRepairOrderListByApplyId(wbRepairApply.getId());
        //如果状态是待支付  则计算金额
        if(!ObjectUtils.isEmpty(wbRepairApplyDto.getStatus())&&wbRepairApplyDto.getStatus().equals(WbRepairApplyOrderType.UNPAID.getCode())){
            BigDecimal reduce=new BigDecimal("0");
            if (!CollectionUtils.isEmpty(wbRepairApplyDto.getDeviceRenewInfos())){
                reduce=reduce.add(wbRepairApplyDto.getDeviceRenewInfos().stream().map(DeviceRenewInfoDto::getDeviceRenewMoney).reduce(BigDecimal.ZERO, BigDecimal::add));
            }
            wbRepairOrder.setPayMoney(reduce.add(new BigDecimal(wbRepairApplyDto.getManHourCost()).multiply(new BigDecimal(wbRepairApplyDto.getManHour()))).toString());
            wbRepairOrder.setDeviceRenewMoney(reduce.toString());
            wbRepairOrder.setDeviceRenewInfo(!CollectionUtils.isEmpty(wbRepairApplyDto.getDeviceRenewInfos())?JSONUtil.toJsonStr(wbRepairApplyDto.getDeviceRenewInfos()):"");
            wbRepairOrder.setOrderStatus(WbRepairApplyOrderType.UNPAID.getCode());
            wbRepairOrder.setManHour(wbRepairApplyDto.getManHour());
            wbRepairOrder.setManHourCost(wbRepairApplyDto.getManHourCost());
        }
          //修改订单状态同时新增消息
        if (!CollectionUtils.isEmpty(wbRepairOrders)){
            wbRepairOrder.setId(wbRepairOrders.get(0).getId());
            wbRepairOrder.setOrderStatus(wbRepairApplyDto.getStatus());
            wbRepairOrder.setRecordIfRead(1);//维修记录红点
             if (!ObjectUtils.isEmpty(wbRepairApplyDto.getRepairerId())){
                 wbRepairOrder.setRepairerId(wbRepairApplyDto.getRepairerId());
             }
            if (wbRepairOrderMapper.updateWbRepairOrder(wbRepairOrder)==0){
                throw new RuntimeException("修改订单状态失败");
            }
            //新增消息

            WbInform wbInform = new WbInform();
            wbInform.setClientId(repairApply.getApplyerId());
            wbInform.setClientName(repairApply.getApplyerName());
            wbInform.setRelevantBillsId(Long.parseLong(wbRepairOrder.getId()));
            wbInform.setInformType(WbInformType.ORDER_NOTICE.getCode());
            wbInform.setTitle("订单被修改");
            wbInform.setContent("你报修的设备:"+(ObjectUtils.isEmpty(wbRepairApplyDto.getDevice())?repairApply.getDevice():wbRepairApplyDto.getDevice())
                    +"预约上门时间为:"+ (ObjectUtils.isEmpty(wbRepairApplyDto.getNewArriveTime())?ObjectUtils.isEmpty(repairApply.getNewArriveTime())?ObjectUtils.isEmpty(wbRepairApplyDto.getSubscribeDate())?repairApply.getSubscribeDate():wbRepairApplyDto.getSubscribeDate(): DateUtils.dateTime(repairApply.getNewArriveTime()) :DateUtils.dateTime(wbRepairApplyDto.getNewArriveTime()))
                    +"当前受理状态为:"+WbRepairApplyOrderType.getMessage(wbRepairApplyDto.getStatus()));
            wbInform.setCreateTime(DateUtils.getNowDate());

            if (ObjectUtils.isEmpty(wbRepairApplyDto.getIfVx())){
                wbInform.setCreateBy(sysUser.getUserName());
                wbInform.setUpdateBy(sysUser.getUserName());
            }
            wbInform.setUpdateTime(DateUtils.getNowDate());
            wbInform.setIfRead(WbInformType.UNREAD.getCode());
            wbInform.setDelFlag(WbInformType.EXIST.getCode());
            if (wbInformMapper.insertWbInform(wbInform)==0){
                throw new RuntimeException("新增信息失败");
            }
        }

        return i;
    }

    /**
     * 批量删除报修申请
     * 
     * @param ids 需要删除的报修申请主键
     * @return 结果
     */
    @Override
    @Transactional
    public int deleteWbRepairApplyByIds(Long[] ids)
    {
        if (ArrayUtils.isEmpty(ids)){
            return 0;
        }
        //查询 要删除的报修申请列表
        List<WbRepairApply> wbRepairApplyList = wbRepairApplyMapper.selectWbRepairApplyByIds(Arrays.asList(ids));
        //筛选出状态为 待开始的
        String[] repairApplyIds = wbRepairApplyList.stream().filter(item -> item.getStatus() <= WbRepairApplyOrderType.TO_BE_STARTED.getCode()||item.getStatus()==WbRepairApplyOrderType.CANCELLATION.getCode())
                .map(item -> item.getId().toString()).toArray(String[]::new);

        if (repairApplyIds.length==0){
            throw  new RuntimeException("只能删除待开始的订单");
        }
        //删除报修申请
        int i = wbRepairApplyMapper.deleteWbRepairApplyByIds(ids);
        //如果没有 要删除的订单则直接返回
        List<WbRepairOrder> wbRepairOrderList= wbRepairOrderMapper.selectWbRepairOrderByRepairApplyIds(repairApplyIds);
        if(CollectionUtils.isEmpty(wbRepairOrderList)){
            return i;
        }

        //根据  报修申请id  删除 订单申请
        int j = wbRepairOrderMapper.deleteWbRepairOrderByRepairApplyIds(repairApplyIds);
        //如果删除数量对不上则回滚

        return i;
    }

    /**
     * 删除报修申请信息
     * 
     * @param id 报修申请主键
     * @return 结果
     */
    @Override
    @Transactional
    public int deleteWbRepairApplyById(Long id)
    {


        WbRepairApply wbRepairApply = wbRepairApplyMapper.selectWbRepairApplyById(id);
        if (ObjectUtils.isEmpty(wbRepairApply)){
            return 0;
        }

        //报修状态为  待开始 之前  则用户可以 删除 报修申请   并且删除订单
        if (!(wbRepairApply.getStatus()<= WbRepairApplyOrderType.TO_BE_STARTED.getCode())){
         return 0;
        }
        int i = wbRepairApplyMapper.deleteWbRepairApplyById(id);
         if (i==0){
             throw new RuntimeException("删除报修失败");
         }
        ArrayList<String> strings = new ArrayList<>();
        strings .add(wbRepairApply.getId().toString());
        String[] applyIdsArray = strings.toArray(new String[1]);
        List<WbRepairOrder> wbRepairOrderList = wbRepairOrderMapper.selectWbRepairOrderByRepairApplyIds(applyIdsArray);
        //如果是空的则不用删除订单
         if (CollectionUtils.isEmpty(wbRepairOrderList)){
             return i;
         }

        //根据  报修申请id  删除 订单申请
        int j= wbRepairOrderMapper.deleteWbRepairOrderByRepairApplyId(wbRepairApply.getId());
        if (j==0){
            throw new RuntimeException("删除订单失败");
        }

        return i;
    }

    @Override
    public Map<String,Boolean> getRedDot() {
        HashMap<String, Boolean> result = new HashMap<>();
        SysUser user = SecurityUtils.getLoginUser().getUser();
      int i=  wbRepairOrderMapper.getRedDotMaster(user.getUserId());
      int j=  wbRepairOrderMapper.getRedDotRecord(user.getUserId());
      result.put("masterRedDot",i>0);
      result.put("recordRedDot",j>0);
      return result;
    }

    @Override
    public int putRedDot(Map<String,Long> ifMaster) {
        SysUser user = SecurityUtils.getLoginUser().getUser();
        if (ifMaster.get("ifMaster").equals(1L)){
            wbRepairOrderMapper.putRedDotMaster(user.getUserId());
        }else {
            wbRepairOrderMapper.putRedDotRecord(user.getUserId());
        }



       return 1;
    }

}
